package com.sojson.util.xlwb;

import java.util.HashMap;

import com.alibaba.fastjson.JSONObject;
import com.sojson.config.exception.TransErrorCode;
import com.sojson.constant.Constant;
import com.sojson.enums.core.ESex;
import com.sojson.result.bean.Status;
import com.sojson.util.OtherUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.bean.OtherUser;
import com.sojson.util.httpclient.HttpClientUtil;
import com.sojson.util.json.JsonUtil;

/**
 * 新浪微博工具类
 * 
 * @author liu
 * @date 2020-09-09
 */
public class XlwbUtil {

    /** ----------------------------以下是静态属性---------------------------- */
    /** ----------------------------以下是静态属性---------------------------- */
    /** ----------------------------以下是静态属性---------------------------- */
    /** 性别: 未知 */
    private static final String FIELD_UNKNOWN = "n";
    /** 性别: 男 */
    private static final String FIELD_MAN = "m";
    /** 性别: 女 */
    private static final String FIELD_GIRL = "f";

    /** ----------------------------以下是新浪微博用户帐号---------------------------- */
    /** ----------------------------以下是新浪微博用户帐号---------------------------- */
    /** ----------------------------以下是新浪微博用户帐号---------------------------- */
    /** 类似帐号 */
    public static final String APPID = Constant.PROPERTIES.getProperty("so.xlwb.appid");
    /** 类似密码 */
    public static final String APPSECRET = Constant.PROPERTIES.getProperty("so.xlwb.appsecret");

    /** ----------------------------以下是新浪微博接口返回的参数---------------------------- */
    /** ----------------------------以下是新浪微博接口返回的参数---------------------------- */
    /** ----------------------------以下是新浪微博接口返回的参数---------------------------- */
    // =======================================================================================================
    // =================================================用户信息================================================
    // =======================================================================================================
    /** 参数: id(用户的UID,和UID相同) */
    public static final String FIELD_ID = "id";
    /** 参数: screen_name(昵称) */
    public static final String FIELD_SCREEN_NAME = "screen_name";
    /** 参数: province(省级ID) */
    public static final String FIELD_PROVINCE = "province";
    /** 参数: city(城市ID) */
    public static final String FIELD_CITY = "city";
    /** 参数: location(详细地址) */
    public static final String FIELD_LOCATION = "location";
    /** 参数: gender(性别) */
    public static final String FIELD_GENDER = "gender";
    /** 参数: avatar_hd(头像) */
    public static final String FIELD_AVATAR_HD = "avatar_hd";
    // =======================================================================================================
    // =======================================================================================================
    // =======================================================================================================
    /** 参数: client_id(申请应用时分配的AppKey) */
    public static final String FIELD_CLIENT_ID = "client_id";
    /** 参数: client_secret(申请应用时分配的AppSecret) */
    public static final String FIELD_CLIENT_SECRET = "client_secret";
    /** 参数: grant_type(请求的类型) */
    public static final String FIELD_GRANT_TYPE = "grant_type";
    /** 值: grant_type_value(通过code获取access_token) */
    public static final String FIELD_GRANT_TYPE_VALUE = "authorization_code";
    /** 参数: redirect_uri(回调地址) */
    public static final String FIELD_REDIRECT_URI = "redirect_uri";
    /** 参数: access_token(用户授权的唯一票据,用于调用微博的开放接口) */
    public static final String FIELD_ACCESS_TOKEN = "access_token";
    /** 参数: uid(授权用户的UID) */
    public static final String FIELD_UID = "uid";
    /** 参数: expires_in(access_token的生命周期,单位是秒) */
    public static final String FIELD_EXPIRES_IN = "expires_in";
    // =======================================================================================================
    // =================================================状态码=================================================
    // =======================================================================================================
    /** 参数: code */
    public static final String FIELD_CODE = "code";
    /** 参数: error */
    public static final String FIELD_ERROR_MESSAGE = "error";
    /** 参数: error_code */
    public static final String FIELD_ERROR_CODE = "error_code";
    /** 参数: error_description */
    public static final String FIELD_ERROR_DESCRIPTION_MESSAGE = "error_description";

    /** ----------------------------以下是新浪微博访问地址---------------------------- */
    /** ----------------------------以下是新浪微博访问地址---------------------------- */
    /** ----------------------------以下是新浪微博访问地址---------------------------- */
    /** 新浪微博WEB端获取认证CODE的路径 */
    public static final String WEB_CODE_URL =
        StringUtil.isNotBlank(Constant.PROPERTIES.getProperty("so.xlwb.web.codeUrl"))
            ? String.format(Constant.PROPERTIES.getProperty("so.xlwb.web.codeUrl"), APPID, "%s", "%s") : "";
    /** 新浪微博移动端获取认证CODE的路径 */
    public static final String MOBILE_CODE_URL =
        StringUtil.isNotBlank(Constant.PROPERTIES.getProperty("so.xlwb.mobile.codeUrl"))
            ? String.format(Constant.PROPERTIES.getProperty("so.xlwb.mobile.codeUrl"), APPID, "%s", "%s") : "";
    /** 获取用户认证AccessToken的路径 */
    public static final String USER_ACCESS_TOKEN_URL =
        StringUtil.isNotBlank(Constant.PROPERTIES.getProperty("so.xlwb.userAccessTokenUrl"))
            ? String.format(Constant.PROPERTIES.getProperty("so.xlwb.userAccessTokenUrl"), APPID, APPSECRET, "%s") : "";
    /** 获取新浪微博用户信息的路径 */
    public static final String USER_INFO_URL = Constant.PROPERTIES.getProperty("so.xlwb.userInfoUrl");

    /**
     * 获取新浪微博用户认证AccessToken
     * 
     * @param code 新浪微博用户登录新浪微博平台后,新浪微博平台返回给回调接口的code
     * @return
     * @throws Exception
     */
    public static XlwbBean getUserAccessToken(String code) throws Exception {
        HashMap<String, String> hashMap = new HashMap<>(6);
        hashMap.put(FIELD_CLIENT_ID, APPID);
        hashMap.put(FIELD_CLIENT_SECRET, APPSECRET);
        hashMap.put(FIELD_GRANT_TYPE, FIELD_GRANT_TYPE_VALUE);
        hashMap.put(FIELD_REDIRECT_URI, OtherUtil.AUTHC_CODE_CALL_BACK);
        hashMap.put(FIELD_CODE, code);

        String urlResult = HttpClientUtil.doPostByParam(USER_ACCESS_TOKEN_URL, hashMap);
        if (StringUtil.isBlankObject(urlResult)) {
            return new XlwbBean(TransErrorCode.OTHER_ERROR.getCode(), "通过CODE获取新浪微博用户认证AccessToken,路径没有返回任何值!");
        }

        JSONObject jsonObject = JsonUtil.jsonToObject(urlResult, JSONObject.class);
        Integer errorCode = jsonObject.getInteger(FIELD_ERROR_CODE);
        if (StringUtil.isNotBlankObject(errorCode)) {
            return new XlwbBean(errorCode, jsonObject.getString(FIELD_ERROR_DESCRIPTION_MESSAGE));
        }

        XlwbBean xlwbBean = new XlwbBean(TransErrorCode.SUCCESS.getCode());
        xlwbBean.setAccessToken(jsonObject.getString(FIELD_ACCESS_TOKEN));
        xlwbBean.setUid(jsonObject.getString(FIELD_UID));
        return xlwbBean;
    }

    /**
     * 获取新浪微博用户的信息
     * 
     * @param code 新浪微博用户登录新浪微博平台后,新浪微博平台返回给回调接口的code
     * @return
     * @throws Exception
     */
    public static OtherUser getUserMessage(String code) throws Exception {
        XlwbBean userAccessToken = getUserAccessToken(code);
        Status status = userAccessToken.getStatus();
        if (status.getCode() == TransErrorCode.SUCCESS.getCode()) {
            return getUserMessage(userAccessToken);
        }

        return new OtherUser(userAccessToken.getStatus());
    }

    /**
     * 获取新浪微博用户的信息
     * 
     * @param wxBean 通过WxUtils.getUserAccessToken(String code)查出来的WxBean
     * @return
     * @throws Exception
     */
    public static OtherUser getUserMessage(XlwbBean wxBean) throws Exception {
        String urlResult = HttpClientUtil.doGet(String.format(USER_INFO_URL, wxBean.getAccessToken(), wxBean.getUid()));
        if (StringUtil.isBlankObject(urlResult)) {
            return new OtherUser(TransErrorCode.OTHER_ERROR.getCode(), "通过WEB端新浪微博用户认证AccessToken获取用户信息,路径没有返回任何值!");
        }

        JSONObject jsonObject = JsonUtil.jsonToObject(urlResult, JSONObject.class);
        Integer errorCode = jsonObject.getInteger(FIELD_ERROR_CODE);
        if (StringUtil.isNotBlankObject(errorCode)) {
            return new OtherUser(errorCode, jsonObject.getString(FIELD_ERROR_MESSAGE));
        }

        OtherUser user = new OtherUser(TransErrorCode.SUCCESS.getCode());
        user.setAppId(jsonObject.getString(FIELD_ID));
        user.setNickname(jsonObject.getString(FIELD_SCREEN_NAME));
        String sex = jsonObject.getString(FIELD_GENDER);
        if (FIELD_UNKNOWN.equals(sex)) {
            user.setSex(ESex.UNKNOWN.getCode());
        } else if (FIELD_MAN.equals(sex)) {
            user.setSex(ESex.MAN.getCode());
        } else if (FIELD_GIRL.equals(sex)) {
            user.setSex(ESex.GIRL.getCode());
        }
        user.setHeadImg(jsonObject.getString(FIELD_AVATAR_HD));
        user.setProvince(jsonObject.getInteger(FIELD_PROVINCE));
        user.setCity(jsonObject.getInteger(FIELD_CITY));
        user.setArea(jsonObject.getString(FIELD_LOCATION));
        return user;
    }

}